package icu.d4peng.basic.satoken;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.basic.SaBasicTemplate;
import cn.dev33.satoken.basic.SaBasicUtil;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.context.second.SaTokenSecondContextCreator;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.log.SaLog;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.same.SaSameTemplate;
import cn.dev33.satoken.sign.SaSignTemplate;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.temp.SaTempInterface;
import icu.d4peng.basic.satoken.filter.SaPathCheckFilterForServlet;
import icu.d4peng.basic.satoken.properties.SaSsoProperties;
import icu.d4peng.basic.satoken.properties.SaTokenProperties;
import icu.d4peng.basic.satoken.spring.SaTokenContextForSpring;
import icu.d4peng.basic.satoken.spring.context.path.ApplicationContextPathLoading;
import icu.d4peng.basic.satoken.spring.json.SaJsonTemplateForJackson;
import icu.d4peng.basic.satoken.spring.pathmatch.SaPathMatcherHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.util.Assert;
import org.springframework.util.PathMatcher;

import java.util.List;
import java.util.Objects;

/**
 * SaTokenAutoConfiguration:token自动配置
 *
 * @author d4peng <a href="d4peng@qq.com">d4peng@qq.com</a>
 * @since 2023.12.02
 */
@AutoConfiguration
@EnableConfigurationProperties({ SaTokenProperties.class })
@ConditionalOnClass(SaTokenConfig.class)
@ConditionalOnProperty(prefix = SaTokenProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class SaTokenAutoConfiguration {

	public SaTokenAutoConfiguration(@Autowired(required = false) SaLog saLog,
			@Autowired(required = false) SaTokenProperties saTokenProperties,
			@Autowired(required = false) SaTokenDao saTokenDao, @Autowired(required = false) StpInterface stpInterface,
			@Autowired(required = false) SaTokenContext saTokenContext,
			@Autowired(required = false) SaTokenSecondContextCreator saTokenSecondContextCreator,
			@Autowired(required = false) List<SaTokenListener> saTokenListenerList,
			@Autowired(required = false) SaTempInterface saTempInterface,
			@Autowired(required = false) SaSameTemplate saSameTemplate,
			@Autowired(required = false) SaBasicTemplate saBasicTemplate,
			@Autowired(required = false) SaJsonTemplate saJsonTemplate,
			@Autowired(required = false) SaSignTemplate saSignTemplate, @Autowired(required = false) StpLogic stpLogic,
			@Autowired(required = false) @Qualifier("mvcPathMatcher") PathMatcher pathMatcher) {
		Assert.notNull(saTokenProperties, "saTokenConfig can't be null");
		if (saLog != null) {
			SaManager.setLog(saLog);
		}
		SaManager.setConfig(saTokenProperties.setIsPrint(false));
		if (saTokenDao != null) {
			SaManager.setSaTokenDao(saTokenDao);
		}
		if (stpInterface != null) {
			SaManager.setStpInterface(stpInterface);
		}
		SaManager.setSaTokenContext(Objects.requireNonNullElseGet(saTokenContext, SaTokenContextForSpring::new));
		if (saTokenSecondContextCreator != null) {
			SaManager.setSaTokenSecondContext(saTokenSecondContextCreator.create());
		}
		if (saTokenListenerList != null) {
			SaTokenEventCenter.registerListenerList(saTokenListenerList);
		}
		if (saTempInterface != null) {
			SaManager.setSaTemp(saTempInterface);
		}
		if (saSameTemplate != null) {
			SaManager.setSaSameTemplate(saSameTemplate);
		}
		if (saBasicTemplate != null) {
			SaBasicUtil.saBasicTemplate = saBasicTemplate;
		}
		SaManager.setSaJsonTemplate(Objects.requireNonNullElseGet(saJsonTemplate, SaJsonTemplateForJackson::new));
		if (saSignTemplate != null) {
			SaManager.setSaSignTemplate(saSignTemplate);
		}
		if (stpLogic != null) {
			StpUtil.setStpLogic(stpLogic);
		}
		if (pathMatcher != null) {
			SaPathMatcherHolder.setPathMatcher(pathMatcher);
		}
	}

	/**
	 * 应用上下文路径加载器
	 * @return /
	 */
	@Bean
	public ApplicationContextPathLoading getApplicationContextPathLoading() {
		return new ApplicationContextPathLoading();
	}

	/**
	 * 请求 path 校验过滤器
	 * @return /
	 */
	@Bean
	public SaPathCheckFilterForServlet saPathCheckFilterForServlet() {
		return new SaPathCheckFilterForServlet();
	}

}
